<template>
  <a-select mode="multiple" :value="value" @change="onChange" @popupScroll="onPopupScroll" :filterOption="onFilterOption" placeholder="请输入姓名进行查询/多选" @search="onSearch">
    <a-select-option :key="item.id" v-for="(item, index) in renderList" :value="item.id">{{ index }}、{{ item.name }}({{ completeDataList.length }})</a-select-option>
  </a-select>
</template>

<script>
import { getOneOrgUsers } from '@/api/commons.js'

export default {
  name: 'PagingSelection',
  props: {},
  data() {
    return {
      value: [], //  选中项
      completeDataList: [], //  全量数据列表，数据会在不同场景下移入 renderList，准确的说：completeDataList + renderList 才是全量数据
      renderList: [], //  渲染列表
      // 请求参数
      params: {
        pageNumber: 1,
        pageSize: 20,
        rootOrgId: '',
        nameLike: null,
        types: [0]
      }
    }
  },
  watch: {
    value: {
      handler(newVal) {
        this.showBack()
      },
      immediate: true
    }
  },

  created() {
    this.getData()
    // 伪代码：模拟异步获取数据
    // setTimeout(() => {
    //   // 钟明志，张楚滢
    //   this.value = ['0009a7e4acbf4a4a88de12d72e6464d6', '00bd063236c141eebd8ddf737f87f40c']
    // }, 20000)
  },
  beforeDestory() {},
  methods: {
    /**
     * 获取数据
     */
    async getData() {
      let params = this.$clone(this.params)
      params.pageSize = 99999 //  直接查全量数据，前端进行筛选、分页等逻辑处理
      // params.pageSize = 17

      const res = await getOneOrgUsers(params)
      if (res.code === 200) {
        this.completeDataList = res.data.list
        this.showBack()
        this.generateRenderList()
      }
    },
    /**
     * 触发滚动，手动节流
     */
    onPopupScroll(e) {
      clearTimeout(this.scrollTimer)
      this.scrollTimer = setTimeout(() => {
        const { target } = e
        const { scrollTop, offsetHeight, scrollHeight } = target

        if (scrollTop + offsetHeight + 50 >= scrollHeight) {
          this.generateRenderList()
        }
      }, 500)
    },
    /**
     * 生成渲染列表
     */
    generateRenderList() {
      const completeLen = this.completeDataList.length
      if (completeLen > 0) {
        const arr = this.completeDataList.splice(0, 20) //  一次加载 20 项
        this.renderList.push(...arr)
      }
    },
    /**
     * a-select 组件默认根据 value 进行搜索，通过该方法改为根据 label 进行搜索
     */
    onFilterOption(inputValue, option) {
      return option.componentOptions.children[0].text.includes(inputValue)
    },
    /**
     * 进行搜索时，从全量数据表中查找是否存在被搜索项
     * 如果存在，将之移入渲染列表
     * 递归以上操作，直至全量数据表中不存在被搜索项
     */
    onSearch(value) {
      if ([null, undefined, ''].includes(value)) return
      const idx = this.completeDataList.findIndex(item => item.name.includes(value))
      if (idx === -1) return //  如果全量数据表已经不存在
      const itemNeedTrans = this.completeDataList.splice(idx, 1)
      this.renderList.push(...itemNeedTrans)
      this.onSearch(value) //  递归
    },
    /**
     * 选中项变更事件
     */
    onChange(value, option) {
      this.value = value
      this.$emit('change', value)
    },
    /**
     * 用于回显
     * 场景1：先拿到 value 值，后拿到全量列表数据
     *    此时需要在拿到全量列表数据后，从全量列表数据中找到 value 对应的项，将其放到 renderList 中，以便实现回显
     * 场景2：先拿到全量列表数据，后拿到 value 值
     *    此时在 watch 中监听 value 的值，拿到 value 值后，去全量列表中找到 value 对应的项，存入 renderList
     */
    showBack() {
      this.value.forEach(str => {
        const idx = this.completeDataList.findIndex(item => item.id === str)
        if (idx === -1) return
        const itemNeedTrans = this.completeDataList.splice(idx, 1)
        this.renderList.push(...itemNeedTrans)
      })
    }
  }
}
</script>

<style scoped lang="less"></style>
